using System;
using System.Text;
using System.Runtime.InteropServices;

using Tomboy;
using Dashboard;

namespace Tomboy.Dashboard
{
	public class DashboardNoteAddin : NoteAddin
	{
		private const int typing_timeout = 1500;
		private uint typing_timeout_id = (uint) 0;

		private Connection connection;
		private StringBuilder buffer;

		public override void Initialize ()
		{
		}

		public override void Shutdown ()
		{
		}

		public override void OnNoteOpened ()
		{
			Note.Window.Shown += OnWindowShown;
			Note.Buffer.InsertText += OnTextInserted;
		}

		private void OnWindowShown (object o, EventArgs args)
		{
			if (connection == null) {
				try {
					connection = Connection.Create ();
				} catch (Exception ex) {
					return;
				}
			}

			ClueMessage clue_message = new ClueMessage ();
			clue_message.Path = "/event/document/opened";
			clue_message.Window = (ulong) gdk_x11_drawable_get_xid (Note.Window.GdkWindow.Handle);

			Clue document_clue = new Clue ("db:document");
			document_clue.Properties.Add (new Property ("dc:title", "dc:string", Note.Title));
			document_clue.Properties.Add (new Property ("dc:content", "dc:text", Note.TextContent));

			clue_message.Clues.Add (document_clue);

			try {
				connection.Send (clue_message);
			} catch (Exception ex) {
				Logger.Debug ("Caught exception while sending message to Dashboard: {0}", ex.Message);
				connection = null;
			}
		}

		private void OnTextInserted (object sender, Gtk.InsertTextArgs args)
		{
			if (typing_timeout_id != (uint) 0)
				Gtk.Timeout.Remove (typing_timeout_id);

			if (buffer == null)
				buffer = new StringBuilder ();

			buffer.Append (args.Text);

			typing_timeout_id = Gtk.Timeout.Add (typing_timeout, OnTypingTimeout);
		}

		private bool OnTypingTimeout ()
		{
			if (connection == null) {
				try {
					connection = Connection.Create ();
				} catch (Exception ex) {
					return false;
				}
			}

			ClueMessage clue_message = new ClueMessage ();
			clue_message.Path = "/event/document/typing";
			clue_message.Window = (ulong) gdk_x11_drawable_get_xid (Note.Window.GdkWindow.Handle);

			Clue document_clue = new Clue ("db:document");
			document_clue.Properties.Add (new Property ("dc:title", "dc:string", Note.Title));
			document_clue.Properties.Add (new Property ("dc:content", "dc:text", Note.TextContent));

			Clue sentence_clue = new Clue ("db:sentence");
			sentence_clue.Properties.Add (new Property ("dc:content", "dc:text", buffer.ToString ()));

			clue_message.Clues.Add (document_clue);
			clue_message.Clues.Add (sentence_clue);

			try {
				connection.Send (clue_message);
			} catch (Exception ex) {
				Logger.Debug ("Caught exception while sending message to Dashboard: {0}", ex.Message);
				connection = null;
			}

			buffer.Length = 0;
			return false;
		}

		[DllImport("libgdk-x11-2.0.so")]
		extern static UIntPtr gdk_x11_drawable_get_xid(IntPtr window);
	}
}
